﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EBookStore.Management
{
    [AOP.Trace]
    public class UsersManager
    {

        List<Users.User> _users;

        /// <summary>
        /// LIst of all users.
        /// </summary>
        public List<Users.User> Users
        {
            get { return _users; }            
        }


        #region Singleton
        
        private static UsersManager _instance = null;
        private static object _syncObj = new object();



        /// <summary>
        /// PublisherManager instance
        /// </summary>
        public static UsersManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_syncObj)
                    {
                        if (_instance == null)
                        {
                            _instance = new UsersManager();
                        }
                    }
                }
                return _instance;
            }
        }


        private UsersManager()
        {
            _users = new List<Users.User>();                        
        } 

        #endregion


        #region Public Functions

        /// <summary>
        /// Adds new user to system
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [AOP.NotNullOrConcreteObject(Index = 0, BaseType = typeof(Users.User), Message = "User is null")]
        public bool AddUser(Users.User user)
        {
            var u = (from el in _users where el.ID.Equals(user.ID) select el).FirstOrDefault();
            if (u != null)
            {
                throw new Exception("User with such id exists");
            }
            else
            {
                _users.Add(user);
                return true;
            }
        }


        /// <summary>
        /// Returns list of users that should recieve message about order cancelation.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Users.User> GetUsersForOrderCancelationAcknowledge()
        {
            return (from el in _users where el.GetType() == typeof(Users.Clerk) select el).ToArray();
        }



        /// <summary>
        /// Login user to the system
        /// </summary>
        /// <param name="login"></param>
        /// <param name="password"></param>
        /// <param name="_users">reference to list of all users</param>
        /// <returns> true if valid user, false if invalid</returns>
        [AOP.NotNullOrConcreteObject(Index = 0, BaseType = typeof(string), Message = "Login is null")]
        [AOP.NotNullOrConcreteObject(Index = 1, BaseType = typeof(string), Message = "Password is null")]
        public bool Login(string login, string password)
        {
            return (from p in _users where p.Login == login && p.Password == password select p).Any();
        }

        /// <summary>
        /// Removes user from system
        /// if such doesn't has any created orders.
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [AOP.NotNullOrConcreteObject(Index = 0, BaseType = typeof(Users.User), Message = "User is null")]
        public bool RemoveUser(Users.User user)
        {
            Orders.Order[] orders = (Orders.Order[])OrdersManager.Instance.GetOrders(user);
            if (orders == null || orders.Length == 0)
            {
                _users.Remove(user);
                return true;
            }
            else
            {
                throw new Exception("User has order/s, can't remove");
            }

        }

        /// <summary>
        /// Remove all users
        /// </summary>
        public void Clear()
        {
            _users.Clear();
        }
        #endregion
    }
}
